package com.zyf.EasyNet.util.NeuralNetwork;

import org.springframework.stereotype.Component;

/**
 * @first_author zyflzz
 * @gmt_created 2022/5/31
 * @gmt_modified 2022/5/31
 */
@Component
public class ActFuncUtils {

    /**
     * 激活函数： sigmoid 函数
     *
     * @param param 函数参数
     * @return 函数值
     */
    public double sigmoid(double param) {
        return 1 / (1 + Math.exp(-param));
    }

    /**
     * sigmoid 函数导数
     *
     * @param param 函数参数
     * @return 函数值
     */
    public double dSigmoid(double param) {
        double f = sigmoid(param);
        return f * (1 - f);
    }

    /**
     * 激活函数： tanh 函数
     *
     * @param param 函数参数
     * @return 函数值
     */
    public double tanh(double param) {
        return Math.tanh(param);
    }

    /**
     * tanh 函数导数
     *
     * @param param 函数参数
     * @return 函数值
     */
    public double dTanh(double param) {
        double f = tanh(param);
        return 1 - f * f;
    }

    /**
     * 激活函数： ReLU 函数
     *
     * @param param 函数参数
     * @return 函数值
     */
    public double ReLU(double param) {
        return param >= 0 ? param : 0.0;
    }

    /**
     * ReLU 函数导数
     *
     * @param param 函数参数
     * @return 函数值
     */
    public double dReLU(double param) {
        return param >= 0 ? 1.0 : 0.0;
    }

    /**
     * 激活函数： LeakyReLU 函数
     *
     * @param param 函数参数
     * @return 函数值
     */
    public double LeakyReLU(double param) {
        return param >= 0 ? param : 0.01 * param;
    }

    /**
     * LeakyReLU 函数导数
     *
     * @param param 函数参数
     * @return 函数值
     */
    public double dLeakyReLU(double param) {
        return param >= 0 ? 1.0 : 0.01;
    }

    /**
     * 激活函数： ELU 函数
     *
     * @param param 函数参数
     * @param a     系数
     * @return 函数值
     */
    public double ELU(double param, double a) {
        return param >= 0 ? param : a * (Math.exp(param) - 1);
    }

    /**
     * ELU 函数导数
     *
     * @param param 函数参数
     * @param a     系数
     * @return 函数值
     */
    public double dELU(double param, double a) {
        return param >= 0 ? 1.0 : a * Math.exp(param);
    }

    /**
     * 激活函数： SoftPlus 函数
     *
     * @param param 函数参数
     * @return 函数值
     */
    public double softPlus(double param) {
        return Math.log(1 + Math.exp(param));
    }

    /**
     * SoftPlus 函数导数
     *
     * @param param 函数参数
     * @return 函数值
     */
    public double dSoftPlus(double param) {
        return Math.exp(param) / (1 + Math.exp(param));
    }

}
